/*
 * Copyright 2018- The Pixie Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

syntax = "proto3";

package px.carnot.planner.dynamic_tracing.ir.logical;

option go_package = "logicalpb";

import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "google/protobuf/duration.proto";

message Argument {
  // Used to reference this argument.
  string id = 1;
  // An expression that accesses a subfield of this argument.
  // For example, "foo" refers to an argument named "foo".
  // And "foo.bar" refers to the "bar" field of argument named "foo".
  //
  // NOTE: This should only be a accessor expression started with the name of an
  // argument.
  string expr = 2;
}

message ReturnValue {
  // Used to reference this return value.
  string id = 1;
  // The expression describes how to access this value.
  // The expression is in the form of `$<return value index>.<field>.<field>`.
  // For example,
  // `$0.i32`, which is the first return value's `i32` field.
  //
  // The index to this return value. This is only meaningful for languages that
  // support multiple return values, like Go. Note that Golang index all return
  // values along with the input arguments (excluding the receiver).
  string expr = 2;
}

// Describes the structure of the data Output.
message Output {
  string name = 1;
  repeated string fields = 2;
}

message OutputAction {
  string output_name = 1;
  // The name of the variables to be output.
  repeated string variable_names = 2;
}

// Describes where to attach a probe.
message Tracepoint {
  string symbol = 1;
}

// Indicates a variable named 'id' should be generated, and represents the latency from function
// entry to return.
message FunctionLatency {
  string id = 1;
}

// Corresponds to a logical probe.
message Probe {
  string name = 1;
  // Where to attach this probe.
  Tracepoint tracepoint = 2;
  // Input arguments of a function.
  repeated Argument args = 3;
  // Return values of a function.
  repeated ReturnValue ret_vals = 4;
  // Latency of a function.
  oneof function_latency_oneof {
    FunctionLatency function_latency = 5;
  }
  // Writes a value to the output table.
  //
  // The variable to be inserted into the output table must be one of the above
  // args, ret_vals, and function_latency.
  repeated OutputAction output_actions = 6;
}

message TracepointSpec {
  // The programs table outputs.
  repeated Output outputs = 1;
  // The probe definition for this tracepoint.
  Probe probe = 2;
}

message BPFTrace {
  // Bpftrace code to be deployed.
  string program = 1;
}

// This cannot replace class UPID in src/shared/metadata/base_types.h, because the C++ UPID is
// created to be compatible with Arrow and uses uint128 for efficient processing.
message UPID {
  // A unique ID for a particular agent.
  uint32 asid = 1;
  // The PID of the running process on a particular node.
  uint32 pid = 2;
  // The start time stamp of the process, used to distinguish between processes having the same
  // PID across different time frame.
  uint64 ts_ns = 3;
}

// Describes the target of attaching a Tracepoint.
message DeploymentSpec {
  message SharedObject {
    // The name of the shared library to trace.
    // The name should not include a path or the version number.
    // E.g. /lib/x86_64-linux-gnu/libc.so.6 -> libc
    string name = 1;
    // A running process which is used to locate the shared library.
    // The shared object must be used by this process.
    // Note, however, that the tracepoint is attached to the shared library; not just this process.
    UPID upid = 2;
  }
  message PodProcess {
    // The name of the Pod.
    repeated string pods = 1;
    // The name of the container inside the above Pod.
    string container = 2;
    // The application processes whose cmdline contains this regexp are selected.
    string process = 3;
  }

  // Describes a map of K8s labels in a namespace that can be used to select a set of pods.
  // Container and/or process can be set to select a target UPID when there are multiple containers
  // or processes in the pods.
  message LabelSelector {
    // The set of label keys and values the target pods have.
    map<string, string> labels = 1;
    // The namespace the target pods are in.
    string namespace = 2;
    // The name of the container in the target pods.
    string container = 3;
    // The application process whose cmdline contains this regexp are selected.
    string process = 4;
  }

  oneof target_oneof {
    // The UPID of a running process.
    // Resolved to an executable.
    UPID upid = 1;
    // An way to specify a shared object to be traced.
    SharedObject shared_object = 2;
    // Describes the target process to attach.
    PodProcess pod_process = 3;
    // Describes pods matching a set of labels, and processes within them.
    LabelSelector label_selector = 4;
  }
}

enum SelectorType {
  NO_CONDITION = 0;  // default if none specified
  MAX_KERNEL = 1;
  MIN_KERNEL = 2;
  HOST_NAME = 3;
  // Other selectors here in the future (e.g. OS version)
}

// One selector can enforce one thing
message TracepointSelector {
  SelectorType selector_type = 1;
  string value = 2;
}

// A logical program, either an application tracepoint, or a bpftrace.
message TracepointDeployment {
  // The name of this deployment. Used to identify this operation.
  string name = 1;
  // The liveness time of the tracepoint, represented in ns. After this time,
  // the tracepoint will be deleted.
  google.protobuf.Duration ttl = 2 [ (gogoproto.customname) = "TTL" ];
  // The target processes of this deployment.
  // Right now this only applies to PXL application tracepoints.
  // May become applicable to bpftrace when we support bpftrace uprobes.
  DeploymentSpec deployment_spec = 3;
  // Describes a TracepointProgram with a output table name.
  message TracepointProgram {
    // The name of the table to hold the output data.
    string table_name = 1;
    // A native PXL tracepoint specification.
    TracepointSpec spec = 2;
    // This applies to bpftrace. Note that only one bpftrace program is allowed.
    BPFTrace bpftrace = 3 [ (gogoproto.customname) = "BPFTrace" ];
    // The selectors to enforce on this deployment. Program will be deployed only to agents that
    // match.
    repeated TracepointSelector selectors = 4;
  }
  repeated TracepointProgram programs = 4;
}
